# -*- coding: utf-8 -*-

import unittest

import testpyknic
import testpyknicpygame



"""
This is the main tester class. It will automatically collect all tests and run
 the tests.
"""

__version__ = '$Id: test.py 164 2008-08-24 19:46:15Z DR0ID $'

import sys
import os
import unittest
import glob
try:
    import coverage
except ImportError:
    try:
        from extern import coverage
    except:
        class _CoverageDummy(object):
            def erase(self): pass
            def start(self): pass
            def stop(self): pass
            def report(mods, ignore_errors=0, show_missing=1):
                sys.stdout.write('no coverage availage')
                
        coverage = _CoverageDummy()


# find the local copy
TESTROOTPATH = os.path.dirname(__file__)
REPOPATH = os.path.normpath(os.path.abspath(os.path.join(TESTROOTPATH, os.pardir)))
sys.path.insert(0, REPOPATH)

import logging
logging.getLogger().setLevel(logging.DEBUG)

import pyknic
pyknic.settings['testing'] = True
pyknic.settings['log_level'] = logging.DEBUG
pyknic.settings['log_to_console'] = True
pyknic.init()
# logging.getLogger('test').addHandler(pyknic.settings['log_file_handler'])
logging.getLogger('test').addHandler(pyknic.settings['log_console_handler'])


COVERAGE_WARNING = \
"""WARNING: Just because a statement is covered by a test case doesn't mean that
         the test case checks that the statement does the right thing. So it's 
         not a good idea to organize your testing around statement coverage or to 
         set targets for statement coverage. However, coverage testing is a good 
         tool for discovering features that haven't been tested and suggesting 
         profitable new areas to test."""


def my_import(name):
    if os.path.isfile(name):
        path, filename = os.path.split(name)
        name = '.'.join((os.path.split(path)[1], os.path.splitext(filename)[0]))
    mod = __import__(name)
    components = name.split('.')
    for comp in components[1:]:
        mod = getattr(mod, comp)
    return mod

def run_them(test_order):
    suites = []
    for testname in test_order:
        module = my_import(testname)
        suites.append(unittest.TestLoader().loadTestsFromModule(module))
    alltests = unittest.TestSuite(suites)
    unittest.TextTestRunner(verbosity=1).run(alltests)

def _get_filenames(root_dir, ext='*.py'):
    src_files = []
    for dirpath, dirnames, filenames in os.walk(root_dir):
        for ex in ext.split(','):
            names = glob.glob(os.path.join(dirpath, ex))
            src_files.extend(names)
    return src_files

def clean_directory(root, ext='*.pyc'):
    del_names = _get_filenames(root, ext)
    for name in del_names:
        try:
            os.remove(name)
        except OSError:
            sys.stdout.write('ERROR: %s could not be deleted %s' % 
                                                            (name, os.linesep))
    
def main():
    # remove *.pyc and *.pyo files first to make coverage more accurat
    pyknic_path = os.path.join(REPOPATH, 'pyknic')
    clean_directory(pyknic_path, '*.pyc,*.pyo')
    
    pyknicpygame_path = os.path.join(REPOPATH, 'pyknicpygame')
    clean_directory(pyknicpygame_path, '*.pyc,*.pyo')

    names = [name for name in _get_filenames(TESTROOTPATH) \
                    if os.path.basename(name).startswith('test') and \
                            name.find('extern') < 0]
    
    # prepare coverage
    coverage.erase()
    
    # tests
    coverage.start()
    run_them(names)
    coverage.stop()
    
    # results
    sys.stdout.write("%s%s%s" % (os.linesep, COVERAGE_WARNING, os.linesep) )
    
    mods = _get_filenames(pyknicpygame_path)
    coverage.report(mods, ignore_errors=0, show_missing=1)
    
    mods = _get_filenames(pyknic_path)
    coverage.report(mods, ignore_errors=0, show_missing=1)

if __name__ == '__main__':
    main()


